package com.googlecode.xcarve.netty.client;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.googlecode.xcarve.common.config.CarveConstances;
import com.googlecode.xcarve.netty.core.DoveFuture;
import com.googlecode.xcarve.object.RPCReponse;
import com.googlecode.xcarve.object.RPCRequest;
import com.googlecode.xcarve.router.ConsistentHashRouter;
import com.googlecode.xcarve.router.Router;
import com.googlecode.xcarve.transport.Client;
import com.googlecode.xcarve.util.ConfigHolder;


/**
 * @author xinyun.d
 * 2014年9月20日
 */
public class CarveTemplate{

	private List<? extends Client> clients;
	private Router router = new ConsistentHashRouter();
	static final Logger logger = LoggerFactory.getLogger(CarveTemplate.class);
	
	
	public CarveTemplate(List<? extends Client> clients) {
		this.clients = clients;
	}
	
	public RPCReponse request(Object object) throws Exception{
		int timeout = ConfigHolder.getIntValue(CarveConstances.SERVICE_WAIT_TIME_OUT, CarveConstances.DEFAULT_TIMEOUT);
		return request(object, timeout);
	}
	
	public RPCReponse request(Object object, int timeout) throws Exception{
		RPCRequest request = (RPCRequest)object;
		Client client = router.select(clients, request);
		DoveFuture futrue = new DoveFuture(request);
		try {
			client.send(request);
		} catch (Exception e) {
			futrue.cancelFutrure();
			throw e;
		}
		futrue.setSendTime();
		if(request.isOneWay()){
			return new RPCReponse(request.getSeqId());
		}else if(request.isAsync()){
			
		}else{
		   return futrue.get(timeout);
		}
		return null;
		
	}
 
	 
	public void changed(List<? extends Client> newClients,String service) {
		List<? extends Client> oldClient = new ArrayList<Client>(this.clients);
		logger.info("xcarve session chanaged. oldClient number={}, now clientnumber={}", oldClient.size(), newClients.size());
		synchronized (this) {
			this.clients = newClients;
			router.update(newClients, service);
		}
		for(Client cl : oldClient){
			cl.close();
		}
	}
}
